﻿// Decompiled with JetBrains decompiler
// Type: System.Web.Razor.Parser.VBCodeParser
// Assembly: System.Web.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
// MVID: 682513D6-F37E-48AC-9909-F3EE103CFF14
// Assembly location: D:\Project\Idea\无人机外网\uav\客户端工程\排查工具\bin\Release\System.Web.Razor.dll

using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Web.Razor.Editor;
using System.Web.Razor.Generator;
using System.Web.Razor.Parser.SyntaxTree;
using System.Web.Razor.Resources;
using System.Web.Razor.Text;
using System.Web.Razor.Tokenizer;
using System.Web.Razor.Tokenizer.Symbols;

namespace System.Web.Razor.Parser
{
  /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Represents a Visual Basic code parser.</summary>
  public class VBCodeParser : TokenizerBackedParser<VBTokenizer, VBSymbol, VBSymbolType>
  {
    internal static ISet<string> DefaultKeywords = (ISet<string>) new HashSet<string>((IEqualityComparer<string>) StringComparer.OrdinalIgnoreCase)
    {
      "functions",
      "code",
      "section",
      "do",
      "while",
      "if",
      "select",
      "for",
      "try",
      "with",
      "synclock",
      "using",
      "imports",
      "inherits",
      "option",
      "helper",
      "namespace",
      "class",
      "layout",
      "sessionstate"
    };
    private Dictionary<VBKeyword, Func<bool>> _keywordHandlers = new Dictionary<VBKeyword, Func<bool>>();
    private Dictionary<string, Func<bool>> _directiveHandlers = new Dictionary<string, Func<bool>>((IEqualityComparer<string>) StringComparer.OrdinalIgnoreCase);

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Initializes a new instance of the <see cref="T:System.Web.Razor.Parser.VBCodeParser" /> class.</summary>
    public VBCodeParser()
    {
      this.DirectParentIsCode = false;
      this.Keywords = (ISet<string>) new HashSet<string>((IEqualityComparer<string>) StringComparer.OrdinalIgnoreCase);
      this.SetUpKeywords();
      this.SetUpDirectives();
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Gets the keywords associated with the code.</summary>
    /// <returns>The keywords associated with the code.</returns>
    protected internal ISet<string> Keywords { get; private set; }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Gets the language for the parser.</summary>
    /// <returns>The language for the parser.</returns>
    protected override LanguageCharacteristics<VBTokenizer, VBSymbol, VBSymbolType> Language => (LanguageCharacteristics<VBTokenizer, VBSymbol, VBSymbolType>) VBLanguageCharacteristics.Instance;

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Gets the other parser.</summary>
    /// <returns>The other parser.</returns>
    protected override ParserBase OtherParser => this.Context.MarkupParser;

    private bool IsNested { get; set; }

    private bool DirectParentIsCode { get; set; }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Determines whether the code is at embedded transition.</summary>
    /// <returns>true if the code is at embedded transition; otherwise, false.</returns>
    /// <param name="allowTemplatesAndComments">true to allow templates and comments; otherwise, false.</param>
    /// <param name="allowTransitions">true to allow transitions; otherwise, false.</param>
    protected override bool IsAtEmbeddedTransition(
      bool allowTemplatesAndComments,
      bool allowTransitions)
    {
      if (allowTransitions && this.Language.IsTransition(this.CurrentSymbol) && !this.Was(VBSymbolType.Dot) || allowTemplatesAndComments && this.Language.IsCommentStart(this.CurrentSymbol))
        return true;
      return this.Language.IsTransition(this.CurrentSymbol) && this.NextIs(VBSymbolType.Transition);
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Handles the embedded transition.</summary>
    protected override void HandleEmbeddedTransition() => this.HandleEmbeddedTransition((VBSymbol) null);

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Handles the embedded transition.</summary>
    /// <param name="lastWhiteSpace">The last white space.</param>
    protected void HandleEmbeddedTransition(VBSymbol lastWhiteSpace)
    {
      if (this.At(VBSymbolType.RazorCommentTransition))
      {
        this.Accept(lastWhiteSpace);
        this.RazorComment();
      }
      else
      {
        if (!this.At(VBSymbolType.Transition) || this.Was(VBSymbolType.Dot))
          return;
        this.HandleTransition(lastWhiteSpace);
      }
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Blocks the parsing.</summary>
    public override void ParseBlock()
    {
      if (this.Context == null)
        throw new InvalidOperationException(RazorResources.Parser_Context_Not_Set);
      using (this.PushSpanConfig())
      {
        if (this.Context == null)
          throw new InvalidOperationException(RazorResources.Parser_Context_Not_Set);
        this.Initialize(this.Span);
        this.NextToken();
        using (this.Context.StartBlock())
        {
          IEnumerable<VBSymbol> symbols = this.ReadWhile((Func<VBSymbol, bool>) (sym => sym.Type == VBSymbolType.WhiteSpace));
          if (this.At(VBSymbolType.Transition))
          {
            this.Accept(symbols);
            this.Span.CodeGenerator = (ISpanCodeGenerator) new StatementCodeGenerator();
            this.Output(SpanKind.Code);
          }
          else
          {
            this.PutBack(symbols);
            this.EnsureCurrent();
          }
          if (this.Optional(VBSymbolType.Transition))
          {
            this.Span.EditHandler.AcceptedCharacters = AcceptedCharacters.None;
            this.Span.CodeGenerator = SpanCodeGenerator.Null;
            this.Output(SpanKind.Transition);
          }
          this.Context.CurrentBlock.Type = new BlockType?(BlockType.Expression);
          this.Context.CurrentBlock.CodeGenerator = (IBlockCodeGenerator) new ExpressionCodeGenerator();
          bool complete = false;
          Action<SpanBuilder> newConfig = (Action<SpanBuilder>) null;
          if (!this.EndOfFile)
          {
            switch (this.CurrentSymbol.Type)
            {
              case VBSymbolType.WhiteSpace:
              case VBSymbolType.NewLine:
                newConfig = new Action<SpanBuilder>(this.ImplictExpressionSpanConfig);
                this.Context.OnError(this.CurrentLocation, RazorResources.ParseError_Unexpected_WhiteSpace_At_Start_Of_CodeBlock_VB);
                break;
              case VBSymbolType.Identifier:
                if (!this.TryDirectiveBlock(ref complete))
                {
                  this.ImplicitExpression();
                  break;
                }
                break;
              case VBSymbolType.Keyword:
                this.Context.CurrentBlock.Type = new BlockType?(BlockType.Statement);
                this.Context.CurrentBlock.CodeGenerator = BlockCodeGenerator.Null;
                complete = this.KeywordBlock();
                break;
              case VBSymbolType.LeftParenthesis:
                complete = this.ExplicitExpression();
                break;
              default:
                newConfig = new Action<SpanBuilder>(this.ImplictExpressionSpanConfig);
                this.Context.OnError(this.CurrentLocation, RazorResources.ParseError_Unexpected_Character_At_Start_Of_CodeBlock_VB, (object) this.CurrentSymbol.Content);
                break;
            }
          }
          else
          {
            newConfig = new Action<SpanBuilder>(this.ImplictExpressionSpanConfig);
            this.Context.OnError(this.CurrentLocation, RazorResources.ParseError_Unexpected_EndOfFile_At_Start_Of_CodeBlock);
          }
          using (this.PushSpanConfig(newConfig))
          {
            if (!complete && this.Span.Symbols.Count == 0 && this.Context.LastAcceptedCharacters != AcceptedCharacters.Any)
              this.AddMarkerSymbolIfNecessary();
            this.Output(SpanKind.Code);
            this.PutCurrentBack();
          }
        }
      }
    }

    private void ImplictExpressionSpanConfig(SpanBuilder span)
    {
      span.CodeGenerator = (ISpanCodeGenerator) new ExpressionCodeGenerator();
      SpanBuilder spanBuilder = span;
      ImplicitExpressionEditHandler expressionEditHandler = new ImplicitExpressionEditHandler(new Func<string, IEnumerable<ISymbol>>(this.Language.TokenizeString), this.Keywords, this.DirectParentIsCode);
      expressionEditHandler.AcceptedCharacters = AcceptedCharacters.NonWhiteSpace;
      spanBuilder.EditHandler = (SpanEditHandler) expressionEditHandler;
    }

    private Action<SpanBuilder> StatementBlockSpanConfiguration(
      SpanCodeGenerator codeGenerator)
    {
      return (Action<SpanBuilder>) (span =>
      {
        span.Kind = SpanKind.Code;
        span.CodeGenerator = (ISpanCodeGenerator) codeGenerator;
        span.EditHandler = SpanEditHandler.CreateDefault(new Func<string, IEnumerable<ISymbol>>(this.Language.TokenizeString));
      });
    }

    private bool TryDirectiveBlock(ref bool complete)
    {
      Func<bool> func;
      if (!this._directiveHandlers.TryGetValue(this.CurrentSymbol.Content, out func))
        return false;
      this.Context.CurrentBlock.CodeGenerator = BlockCodeGenerator.Null;
      complete = func();
      return true;
    }

    private bool KeywordBlock()
    {
      Func<bool> func;
      if (this._keywordHandlers.TryGetValue(this.CurrentSymbol.Keyword.Value, out func))
      {
        this.Span.CodeGenerator = (ISpanCodeGenerator) new StatementCodeGenerator();
        this.Context.CurrentBlock.Type = new BlockType?(BlockType.Statement);
        return func();
      }
      this.ImplicitExpression();
      return false;
    }

    private bool ExplicitExpression()
    {
      this.Context.CurrentBlock.Type = new BlockType?(BlockType.Expression);
      this.Context.CurrentBlock.CodeGenerator = (IBlockCodeGenerator) new ExpressionCodeGenerator();
      SourceLocation currentLocation = this.CurrentLocation;
      this.Expected(VBSymbolType.LeftParenthesis);
      this.Span.CodeGenerator = SpanCodeGenerator.Null;
      this.Span.EditHandler.AcceptedCharacters = AcceptedCharacters.None;
      this.Output(SpanKind.MetaCode);
      this.Span.CodeGenerator = (ISpanCodeGenerator) new ExpressionCodeGenerator();
      using (this.PushSpanConfig((Action<SpanBuilder>) (span => span.CodeGenerator = (ISpanCodeGenerator) new ExpressionCodeGenerator())))
      {
        if (!this.Balance(BalancingModes.BacktrackOnFailure | BalancingModes.NoErrorOnFailure | BalancingModes.AllowCommentsAndTemplates, VBSymbolType.LeftParenthesis, VBSymbolType.RightParenthesis, currentLocation))
        {
          this.Context.OnError(currentLocation, RazorResources.ParseError_Expected_EndOfBlock_Before_EOF, (object) RazorResources.BlockName_ExplicitExpression, (object) VBSymbol.GetSample(VBSymbolType.RightParenthesis), (object) VBSymbol.GetSample(VBSymbolType.LeftParenthesis));
          this.AcceptUntil(VBSymbolType.NewLine);
          this.AddMarkerSymbolIfNecessary();
          this.Output(SpanKind.Code);
          this.PutCurrentBack();
          return false;
        }
        this.AddMarkerSymbolIfNecessary();
        this.Output(SpanKind.Code);
        this.Expected(VBSymbolType.RightParenthesis);
        this.Span.EditHandler.AcceptedCharacters = AcceptedCharacters.None;
        this.Span.CodeGenerator = SpanCodeGenerator.Null;
        this.Output(SpanKind.MetaCode);
        this.PutCurrentBack();
        return true;
      }
    }

    private void ImplicitExpression()
    {
      this.Context.CurrentBlock.Type = new BlockType?(BlockType.Expression);
      this.Context.CurrentBlock.CodeGenerator = (IBlockCodeGenerator) new ExpressionCodeGenerator();
      using (this.PushSpanConfig(new Action<SpanBuilder>(this.ImplictExpressionSpanConfig)))
      {
        this.Expected(VBSymbolType.Identifier, VBSymbolType.Keyword);
        this.Span.CodeGenerator = (ISpanCodeGenerator) new ExpressionCodeGenerator();
        while (!this.EndOfFile)
        {
          switch (this.CurrentSymbol.Type)
          {
            case VBSymbolType.LeftParenthesis:
              SourceLocation currentLocation = this.CurrentLocation;
              this.AcceptAndMoveNext();
              Action<SpanBuilder> oldConfig = this.SpanConfig;
              using (this.PushSpanConfig())
              {
                this.ConfigureSpan((Action<SpanBuilder>) (span =>
                {
                  oldConfig(span);
                  span.EditHandler.AcceptedCharacters = AcceptedCharacters.Any;
                }));
                this.Balance(BalancingModes.AllowCommentsAndTemplates, VBSymbolType.LeftParenthesis, VBSymbolType.RightParenthesis, currentLocation);
              }
              if (this.Optional(VBSymbolType.RightParenthesis))
              {
                this.Span.EditHandler.AcceptedCharacters = AcceptedCharacters.NonWhiteSpace;
                continue;
              }
              continue;
            case VBSymbolType.Dot:
              VBSymbol currentSymbol1 = this.CurrentSymbol;
              this.NextToken();
              if (this.At(VBSymbolType.Identifier) || this.At(VBSymbolType.Keyword))
              {
                this.Accept(currentSymbol1);
                this.AcceptAndMoveNext();
                continue;
              }
              if (this.At(VBSymbolType.Transition))
              {
                VBSymbol currentSymbol2 = this.CurrentSymbol;
                this.NextToken();
                if (this.At(VBSymbolType.Identifier) || this.At(VBSymbolType.Keyword))
                {
                  this.Accept(currentSymbol1);
                  this.Accept(currentSymbol2);
                  this.AcceptAndMoveNext();
                  continue;
                }
                this.PutBack(currentSymbol2);
                this.PutBack(currentSymbol1);
                continue;
              }
              this.PutCurrentBack();
              if (this.IsNested)
              {
                this.Accept(currentSymbol1);
                return;
              }
              this.PutBack(currentSymbol1);
              return;
            default:
              this.PutCurrentBack();
              return;
          }
        }
      }
    }

    /// <summary>Maps a given keyword.</summary>
    /// <param name="keyword">The keyword.</param>
    /// <param name="action">The action whether to map a given keyword.</param>
    protected void MapKeyword(VBKeyword keyword, Func<bool> action)
    {
      this._keywordHandlers[keyword] = action;
      this.Keywords.Add(keyword.ToString());
    }

    /// <summary>Maps a given directive.</summary>
    /// <param name="directive">The directive.</param>
    /// <param name="action">The action whether to map a given directive.</param>
    protected void MapDirective(string directive, Func<bool> action)
    {
      this._directiveHandlers[directive] = action;
      this.Keywords.Add(directive);
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Checks for a condition and displays a keyword in the code.</summary>
    /// <param name="keyword">The keyword.</param>
    [Conditional("DEBUG")]
    protected void Assert(VBKeyword keyword)
    {
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Determines whether the given keyword is ‘AT’.</summary>
    /// <returns>true if the given keyword is ‘AT’; otherwise, false.</returns>
    /// <param name="keyword">The keyword.</param>
    protected bool At(VBKeyword keyword)
    {
      if (!this.At(VBSymbolType.Keyword))
        return false;
      VBKeyword? keyword1 = this.CurrentSymbol.Keyword;
      VBKeyword vbKeyword = keyword;
      return keyword1.GetValueOrDefault() == vbKeyword & keyword1.HasValue;
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Indicates the parser block.</summary>
    protected void OtherParserBlock() => this.OtherParserBlock((string) null, (string) null);

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Indicates the parser block.</summary>
    /// <param name="startSequence">The start sequence.</param>
    /// <param name="endSequence">The end sequence.</param>
    protected void OtherParserBlock(string startSequence, string endSequence)
    {
      using (this.PushSpanConfig())
      {
        if (this.Span.Symbols.Count > 0)
          this.Output(SpanKind.Code);
        this.Context.SwitchActiveParser();
        bool directParentIsCode = this.DirectParentIsCode;
        this.DirectParentIsCode = false;
        if (!string.IsNullOrEmpty(startSequence) || !string.IsNullOrEmpty(endSequence))
          this.Context.MarkupParser.ParseSection(Tuple.Create<string, string>(startSequence, endSequence), false);
        else
          this.Context.MarkupParser.ParseBlock();
        this.DirectParentIsCode = directParentIsCode;
        this.Context.SwitchActiveParser();
        this.EnsureCurrent();
      }
      this.Initialize(this.Span);
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Indicates a code that handles a transition.</summary>
    /// <param name="lastWhiteSpace">The last white space.</param>
    protected void HandleTransition(VBSymbol lastWhiteSpace)
    {
      if (this.At(VBSymbolType.RazorCommentTransition))
      {
        this.Accept(lastWhiteSpace);
        this.RazorComment();
      }
      else
      {
        VBSymbol currentSymbol1 = this.CurrentSymbol;
        this.NextToken();
        if (this.At(VBSymbolType.LessThan) || this.At(VBSymbolType.Colon))
        {
          this.PutCurrentBack();
          this.PutBack(currentSymbol1);
          if (this.Context.DesignTimeMode)
            this.Accept(lastWhiteSpace);
          else
            this.PutBack(lastWhiteSpace);
          this.OtherParserBlock();
        }
        else if (this.At(VBSymbolType.Transition))
        {
          if (this.Context.IsWithin(BlockType.Template))
            this.Context.OnError(currentSymbol1.Start, RazorResources.ParseError_InlineMarkup_Blocks_Cannot_Be_Nested);
          this.Accept(lastWhiteSpace);
          VBSymbol currentSymbol2 = this.CurrentSymbol;
          this.NextToken();
          if (this.At(VBSymbolType.LessThan) || this.At(VBSymbolType.Colon))
          {
            this.PutCurrentBack();
            this.PutBack(currentSymbol2);
            this.PutBack(currentSymbol1);
            this.Output(SpanKind.Code);
            using (this.Context.StartBlock(BlockType.Template))
            {
              this.Context.CurrentBlock.CodeGenerator = (IBlockCodeGenerator) new TemplateBlockCodeGenerator();
              this.OtherParserBlock();
              this.Initialize(this.Span);
            }
          }
          else
          {
            this.Accept(currentSymbol1);
            this.Accept(currentSymbol2);
          }
        }
        else
        {
          this.Accept(lastWhiteSpace);
          this.PutCurrentBack();
          this.PutBack(currentSymbol1);
          bool isNested = this.IsNested;
          this.IsNested = true;
          this.NestedBlock();
          this.IsNested = isNested;
        }
      }
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Spans the output before Razor comment.</summary>
    protected override void OutputSpanBeforeRazorComment() => this.Output(SpanKind.Code);

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Determines whether the code is a reserved word.</summary>
    /// <returns>true if the code is a reserved word; otherwise, false.</returns>
    protected bool ReservedWord()
    {
      this.Context.CurrentBlock.Type = new BlockType?(BlockType.Directive);
      this.Context.OnError(this.CurrentLocation, RazorResources.ParseError_ReservedWord, (object) this.CurrentSymbol.Content);
      this.Span.CodeGenerator = SpanCodeGenerator.Null;
      this.AcceptAndMoveNext();
      this.Output(SpanKind.MetaCode, AcceptedCharacters.None);
      return true;
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Indicates a nested block.</summary>
    protected void NestedBlock()
    {
      using (this.PushSpanConfig())
      {
        this.Output(SpanKind.Code);
        bool directParentIsCode = this.DirectParentIsCode;
        this.DirectParentIsCode = true;
        this.ParseBlock();
        this.DirectParentIsCode = directParentIsCode;
      }
      this.Initialize(this.Span);
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Determines whether the expected symbol is required.</summary>
    /// <returns>true if the expected symbol is required; otherwise, false.</returns>
    /// <param name="expected">The expected symbol.</param>
    /// <param name="errorBase">The error base.</param>
    protected bool Required(VBSymbolType expected, string errorBase)
    {
      if (this.Optional(expected))
        return true;
      this.Context.OnError(this.CurrentLocation, errorBase, (object) this.GetCurrentSymbolDisplay());
      return false;
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Determines whether the keyword from the code is optional.</summary>
    /// <returns>true if the keyword from the code is optional; otherwise, false.</returns>
    /// <param name="keyword">The keyword.</param>
    protected bool Optional(VBKeyword keyword)
    {
      if (!this.At(keyword))
        return false;
      this.AcceptAndMoveNext();
      return true;
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Accepts spaces in the VB code.</summary>
    protected void AcceptVBSpaces() => this.Accept(this.ReadVBSpacesLazy());

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Reads a list of Visual Basic spaces.</summary>
    /// <returns>A list of Visual Basic spaces.</returns>
    protected IEnumerable<VBSymbol> ReadVBSpaces() => (IEnumerable<VBSymbol>) this.ReadVBSpacesLazy().ToList<VBSymbol>();

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Determines whether the code is directive defined.</summary>
    /// <returns>true if the code is directive defined; otherwise, false.</returns>
    /// <param name="directive">The directive.</param>
    public bool IsDirectiveDefined(string directive) => this._directiveHandlers.ContainsKey(directive);

    private IEnumerable<VBSymbol> ReadVBSpacesLazy()
    {
      VBCodeParser vbCodeParser = this;
      foreach (VBSymbol vbSymbol in vbCodeParser.ReadWhileLazy((Func<VBSymbol, bool>) (sym => sym.Type == VBSymbolType.WhiteSpace)))
        yield return vbSymbol;
      while (vbCodeParser.At(VBSymbolType.LineContinuation))
      {
        int absoluteIndex = vbCodeParser.CurrentLocation.AbsoluteIndex;
        VBSymbol currentSymbol = vbCodeParser.CurrentSymbol;
        vbCodeParser.NextToken();
        if (vbCodeParser.At(VBSymbolType.NewLine))
        {
          yield return currentSymbol;
          yield return vbCodeParser.CurrentSymbol;
          vbCodeParser.NextToken();
          foreach (VBSymbol readVbSpace in vbCodeParser.ReadVBSpaces())
            yield return readVbSpace;
        }
        else
        {
          vbCodeParser.Context.Source.Position = absoluteIndex;
          vbCodeParser.NextToken();
          break;
        }
      }
    }

    private void SetUpDirectives()
    {
      this.MapDirective(SyntaxConstants.VB.CodeKeyword, this.EndTerminatedDirective(SyntaxConstants.VB.CodeKeyword, BlockType.Statement, (SpanCodeGenerator) new StatementCodeGenerator(), true));
      this.MapDirective(SyntaxConstants.VB.FunctionsKeyword, this.EndTerminatedDirective(SyntaxConstants.VB.FunctionsKeyword, BlockType.Functions, (SpanCodeGenerator) new TypeMemberCodeGenerator(), false));
      this.MapDirective(SyntaxConstants.VB.SectionKeyword, new Func<bool>(this.SectionDirective));
      this.MapDirective(SyntaxConstants.VB.HelperKeyword, new Func<bool>(this.HelperDirective));
      this.MapDirective(SyntaxConstants.VB.LayoutKeyword, new Func<bool>(this.LayoutDirective));
      this.MapDirective(SyntaxConstants.VB.SessionStateKeyword, new Func<bool>(this.SessionStateDirective));
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Determines whether the code is a layout directive.</summary>
    /// <returns>true if the code is a layout directive; otherwise, false.</returns>
    protected virtual bool LayoutDirective()
    {
      this.AcceptAndMoveNext();
      this.Context.CurrentBlock.Type = new BlockType?(BlockType.Directive);
      bool flag1 = this.At(VBSymbolType.WhiteSpace);
      this.AcceptWhile(VBSymbolType.WhiteSpace);
      this.Output(SpanKind.MetaCode, flag1 ? AcceptedCharacters.None : AcceptedCharacters.Any);
      this.AcceptUntil(VBSymbolType.NewLine);
      this.Span.CodeGenerator = (ISpanCodeGenerator) new SetLayoutCodeGenerator((string) this.Span.GetContent());
      this.Span.EditHandler.EditorHints = EditorHints.VirtualPath | EditorHints.LayoutPage;
      bool flag2 = this.Optional(VBSymbolType.NewLine);
      this.AddMarkerSymbolIfNecessary();
      this.Output(SpanKind.MetaCode, flag2 ? AcceptedCharacters.None : AcceptedCharacters.Any);
      return true;
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Determines whether the code has a session state directive.</summary>
    /// <returns>true if the code has a session state directive; otherwise, false.</returns>
    protected virtual bool SessionStateDirective()
    {
      this.AcceptAndMoveNext();
      this.Context.CurrentBlock.Type = new BlockType?(BlockType.Directive);
      bool flag1 = this.At(VBSymbolType.WhiteSpace);
      this.AcceptWhile(VBSymbolType.WhiteSpace);
      this.Output(SpanKind.MetaCode, flag1 ? AcceptedCharacters.None : AcceptedCharacters.Any);
      this.AcceptUntil(VBSymbolType.NewLine);
      string str = string.Concat(this.Span.Symbols.Select<ISymbol, string>((Func<ISymbol, string>) (sym => sym.Content)));
      this.Span.CodeGenerator = (ISpanCodeGenerator) new RazorDirectiveAttributeCodeGenerator(SyntaxConstants.VB.SessionStateKeyword, str);
      bool flag2 = this.Optional(VBSymbolType.NewLine);
      this.AddMarkerSymbolIfNecessary();
      this.Output(SpanKind.MetaCode, flag2 ? AcceptedCharacters.None : AcceptedCharacters.Any);
      return true;
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Indicates whether the code is a helper directive.</summary>
    /// <returns>true if the code is a helper directive; otherwise, false.</returns>
    protected virtual bool HelperDirective()
    {
      if (this.Context.IsWithin(BlockType.Helper))
        this.Context.OnError(this.CurrentLocation, RazorResources.ParseError_Helpers_Cannot_Be_Nested);
      this.Context.CurrentBlock.Type = new BlockType?(BlockType.Helper);
      SourceLocation currentLocation1 = this.CurrentLocation;
      this.AcceptAndMoveNext();
      VBSymbolType vbSymbolType = VBSymbolType.Unknown;
      if (this.CurrentSymbol != null)
        vbSymbolType = this.CurrentSymbol.Type;
      VBSymbol symbol = (VBSymbol) null;
      if (this.At(VBSymbolType.NewLine))
        this.AcceptAndMoveNext();
      else
        symbol = this.AcceptSingleWhiteSpaceCharacter();
      if (vbSymbolType == VBSymbolType.WhiteSpace || vbSymbolType == VBSymbolType.NewLine)
        this.Span.EditHandler.AcceptedCharacters = AcceptedCharacters.None;
      this.Output(SpanKind.MetaCode);
      if (vbSymbolType != VBSymbolType.WhiteSpace)
      {
        string str;
        if (this.At(VBSymbolType.NewLine))
          str = RazorResources.ErrorComponent_Newline;
        else if (this.EndOfFile)
          str = RazorResources.ErrorComponent_EndOfFile;
        else
          str = string.Format((IFormatProvider) CultureInfo.CurrentCulture, RazorResources.ErrorComponent_Character, (object) this.CurrentSymbol.Content);
        this.Context.OnError(this.CurrentLocation, RazorResources.ParseError_Unexpected_Character_At_Helper_Name_Start, (object) str);
        this.PutCurrentBack();
        this.Output(SpanKind.Code);
        return false;
      }
      if (symbol != null)
        this.Accept(symbol);
      bool flag = !this.Required(VBSymbolType.Identifier, RazorResources.ParseError_Unexpected_Character_At_Helper_Name_Start);
      this.AcceptWhile(VBSymbolType.WhiteSpace);
      SourceLocation currentLocation2 = this.CurrentLocation;
      bool headerComplete = false;
      if (!this.Optional(VBSymbolType.LeftParenthesis))
      {
        if (!flag)
          this.Context.OnError(this.CurrentLocation, RazorResources.ParseError_MissingCharAfterHelperName, (object) VBSymbol.GetSample(VBSymbolType.LeftParenthesis));
      }
      else if (!this.Balance(BalancingModes.NoErrorOnFailure, VBSymbolType.LeftParenthesis, VBSymbolType.RightParenthesis, currentLocation2))
      {
        this.Context.OnError(currentLocation2, RazorResources.ParseError_UnterminatedHelperParameterList);
      }
      else
      {
        this.Expected(VBSymbolType.RightParenthesis);
        headerComplete = true;
      }
      this.AddMarkerSymbolIfNecessary();
      this.Context.CurrentBlock.CodeGenerator = (IBlockCodeGenerator) new HelperCodeGenerator(this.Span.GetContent(), headerComplete);
      AutoCompleteEditHandler completeEditHandler = new AutoCompleteEditHandler(new Func<string, IEnumerable<ISymbol>>(this.Language.TokenizeString));
      this.Span.EditHandler = (SpanEditHandler) completeEditHandler;
      this.Output(SpanKind.Code);
      if (headerComplete)
      {
        bool isNested = this.IsNested;
        this.IsNested = true;
        using (this.Context.StartBlock(BlockType.Statement))
        {
          using (this.PushSpanConfig(this.StatementBlockSpanConfiguration((SpanCodeGenerator) new StatementCodeGenerator())))
          {
            try
            {
              if (this.EndTerminatedDirectiveBody(SyntaxConstants.VB.HelperKeyword, currentLocation1, true))
                return true;
              if (this.Context.LastAcceptedCharacters != AcceptedCharacters.Any)
                this.AddMarkerSymbolIfNecessary();
              completeEditHandler.AutoCompleteString = SyntaxConstants.VB.EndHelperKeyword;
              return false;
            }
            finally
            {
              this.Output(SpanKind.Code);
              this.IsNested = isNested;
            }
          }
        }
      }
      else
      {
        this.Output(SpanKind.Code);
        this.PutCurrentBack();
        return false;
      }
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Determines whether the code is a section directive.</summary>
    /// <returns>true if the code is a section directive; otherwise, false.</returns>
    protected virtual bool SectionDirective()
    {
      SourceLocation currentLocation = this.CurrentLocation;
      this.AcceptAndMoveNext();
      if (this.Context.IsWithin(BlockType.Section))
        this.Context.OnError(this.CurrentLocation, RazorResources.ParseError_Sections_Cannot_Be_Nested, (object) RazorResources.SectionExample_VB);
      if (this.At(VBSymbolType.NewLine))
        this.AcceptAndMoveNext();
      else
        this.AcceptVBSpaces();
      string str = (string) null;
      if (!this.At(VBSymbolType.Identifier))
      {
        this.Context.OnError(this.CurrentLocation, RazorResources.ParseError_Unexpected_Character_At_Section_Name_Start, (object) this.GetCurrentSymbolDisplay());
      }
      else
      {
        str = this.CurrentSymbol.Content;
        this.AcceptAndMoveNext();
      }
      this.Context.CurrentBlock.Type = new BlockType?(BlockType.Section);
      this.Context.CurrentBlock.CodeGenerator = (IBlockCodeGenerator) new SectionCodeGenerator(str ?? string.Empty);
      AutoCompleteEditHandler completeEditHandler = new AutoCompleteEditHandler(new Func<string, IEnumerable<ISymbol>>(this.Language.TokenizeString));
      this.Span.EditHandler = (SpanEditHandler) completeEditHandler;
      this.PutCurrentBack();
      this.Output(SpanKind.MetaCode);
      this.OtherParserBlock((string) null, SyntaxConstants.VB.EndSectionKeyword);
      this.Span.CodeGenerator = SpanCodeGenerator.Null;
      bool flag = false;
      if (!this.At(VBKeyword.End))
      {
        this.Context.OnError(currentLocation, RazorResources.ParseError_BlockNotTerminated, (object) SyntaxConstants.VB.SectionKeyword, (object) SyntaxConstants.VB.EndSectionKeyword);
        completeEditHandler.AutoCompleteString = SyntaxConstants.VB.EndSectionKeyword;
      }
      else
      {
        this.AcceptAndMoveNext();
        this.AcceptWhile(VBSymbolType.WhiteSpace);
        if (!this.At(SyntaxConstants.VB.SectionKeyword))
        {
          this.Context.OnError(currentLocation, RazorResources.ParseError_BlockNotTerminated, (object) SyntaxConstants.VB.SectionKeyword, (object) SyntaxConstants.VB.EndSectionKeyword);
        }
        else
        {
          this.AcceptAndMoveNext();
          this.Span.EditHandler.AcceptedCharacters = AcceptedCharacters.None;
          flag = true;
        }
      }
      this.PutCurrentBack();
      this.Output(SpanKind.MetaCode);
      return flag;
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Ends a terminated directive.</summary>
    /// <returns>The function that ends the terminated directive.</returns>
    /// <param name="directive">The directive.</param>
    /// <param name="blockType">The block type.</param>
    /// <param name="codeGenerator">The code generator.</param>
    /// <param name="allowMarkup">true to allow markup; otherwise, false.</param>
    protected virtual Func<bool> EndTerminatedDirective(
      string directive,
      BlockType blockType,
      SpanCodeGenerator codeGenerator,
      bool allowMarkup)
    {
      return (Func<bool>) (() =>
      {
        SourceLocation currentLocation = this.CurrentLocation;
        this.Context.CurrentBlock.Type = new BlockType?(blockType);
        this.AcceptAndMoveNext();
        this.Span.EditHandler.AcceptedCharacters = AcceptedCharacters.None;
        this.Span.CodeGenerator = SpanCodeGenerator.Null;
        this.Output(SpanKind.MetaCode);
        using (this.PushSpanConfig(this.StatementBlockSpanConfiguration(codeGenerator)))
        {
          AutoCompleteEditHandler completeEditHandler = new AutoCompleteEditHandler(new Func<string, IEnumerable<ISymbol>>(this.Language.TokenizeString));
          this.Span.EditHandler = (SpanEditHandler) completeEditHandler;
          if (this.EndTerminatedDirectiveBody(directive, currentLocation, allowMarkup))
            return true;
          completeEditHandler.AutoCompleteString = SyntaxConstants.VB.EndKeyword + " " + directive;
          return false;
        }
      });
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Determines whether the termination of directive body is ended.</summary>
    /// <returns>true if the termination of directive body is ended; otherwise, false.</returns>
    /// <param name="directive">The directive.</param>
    /// <param name="blockStart">The block start.</param>
    /// <param name="allowAllTransitions">true to allow all transitions; otherwise, false.</param>
    protected virtual bool EndTerminatedDirectiveBody(
      string directive,
      SourceLocation blockStart,
      bool allowAllTransitions)
    {
      while (!this.EndOfFile)
      {
        VBSymbol vbSymbol = this.AcceptWhiteSpaceInLines();
        if (this.IsAtEmbeddedTransition(allowAllTransitions, allowAllTransitions))
          this.HandleEmbeddedTransition(vbSymbol);
        else if (this.At(VBKeyword.End))
        {
          this.Accept(vbSymbol);
          VBSymbol currentSymbol = this.CurrentSymbol;
          this.NextToken();
          IEnumerable<VBSymbol> symbols = this.ReadVBSpaces();
          if (this.At(directive))
          {
            if (this.Context.LastAcceptedCharacters != AcceptedCharacters.Any)
              this.AddMarkerSymbolIfNecessary(currentSymbol.Start);
            this.Output(SpanKind.Code);
            this.Accept(currentSymbol);
            this.Accept(symbols);
            this.AcceptAndMoveNext();
            this.Span.EditHandler.AcceptedCharacters = AcceptedCharacters.None;
            this.Span.CodeGenerator = SpanCodeGenerator.Null;
            this.Output(SpanKind.MetaCode);
            return true;
          }
          this.Accept(currentSymbol);
          this.Accept(symbols);
          this.AcceptAndMoveNext();
        }
        else
        {
          this.Accept(vbSymbol);
          this.AcceptAndMoveNext();
        }
      }
      this.Context.OnError(blockStart, RazorResources.ParseError_BlockNotTerminated, (object) directive, (object) (SyntaxConstants.VB.EndKeyword + " " + directive));
      return false;
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Determines whether the directive is ‘AT’ directive.</summary>
    /// <returns>true if the directive is an ‘AT’ directive; otherwise, false.</returns>
    /// <param name="directive">The directive.</param>
    protected bool At(string directive) => this.At(VBSymbolType.Identifier) && string.Equals(this.CurrentSymbol.Content, directive, StringComparison.OrdinalIgnoreCase);

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Asserts the given directive.</summary>
    /// <param name="directive">The directive to assert.</param>
    [Conditional("DEBUG")]
    protected void AssertDirective(string directive)
    {
    }

    private string GetCurrentSymbolDisplay()
    {
      if (this.EndOfFile)
        return RazorResources.ErrorComponent_EndOfFile;
      if (this.At(VBSymbolType.NewLine))
        return RazorResources.ErrorComponent_Newline;
      if (this.At(VBSymbolType.WhiteSpace))
        return RazorResources.ErrorComponent_Whitespace;
      return string.Format((IFormatProvider) CultureInfo.CurrentCulture, RazorResources.ErrorComponent_Character, (object) this.CurrentSymbol.Content);
    }

    private void SetUpKeywords()
    {
      this.MapKeyword(VBKeyword.Using, this.EndTerminatedStatement(VBKeyword.Using, false, false));
      this.MapKeyword(VBKeyword.While, this.EndTerminatedStatement(VBKeyword.While, true, true));
      this.MapKeyword(VBKeyword.If, this.EndTerminatedStatement(VBKeyword.If, false, false));
      this.MapKeyword(VBKeyword.Select, this.EndTerminatedStatement(VBKeyword.Select, true, false, SyntaxConstants.VB.SelectCaseKeyword));
      this.MapKeyword(VBKeyword.Try, this.EndTerminatedStatement(VBKeyword.Try, true, false));
      this.MapKeyword(VBKeyword.With, this.EndTerminatedStatement(VBKeyword.With, false, false));
      this.MapKeyword(VBKeyword.SyncLock, this.EndTerminatedStatement(VBKeyword.SyncLock, false, false));
      this.MapKeyword(VBKeyword.For, this.KeywordTerminatedStatement(VBKeyword.For, VBKeyword.Next, true, true));
      this.MapKeyword(VBKeyword.Do, this.KeywordTerminatedStatement(VBKeyword.Do, VBKeyword.Loop, true, true));
      this.MapKeyword(VBKeyword.Imports, new Func<bool>(this.ImportsStatement));
      this.MapKeyword(VBKeyword.Option, new Func<bool>(this.OptionStatement));
      this.MapKeyword(VBKeyword.Inherits, new Func<bool>(this.InheritsStatement));
      this.MapKeyword(VBKeyword.Class, new Func<bool>(this.ReservedWord));
      this.MapKeyword(VBKeyword.Namespace, new Func<bool>(this.ReservedWord));
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Determines whether the code inherits a statement.</summary>
    /// <returns>true if the code inherits a statement; otherwise, false.</returns>
    protected virtual bool InheritsStatement()
    {
      this.Span.CodeGenerator = SpanCodeGenerator.Null;
      this.Context.CurrentBlock.Type = new BlockType?(BlockType.Directive);
      this.AcceptAndMoveNext();
      SourceLocation currentLocation = this.CurrentLocation;
      if (this.At(VBSymbolType.WhiteSpace))
        this.Span.EditHandler.AcceptedCharacters = AcceptedCharacters.None;
      this.AcceptWhile(VBSymbolType.WhiteSpace);
      this.Output(SpanKind.MetaCode);
      if (this.EndOfFile || this.At(VBSymbolType.WhiteSpace) || this.At(VBSymbolType.NewLine))
        this.Context.OnError(currentLocation, RazorResources.ParseError_InheritsKeyword_Must_Be_Followed_By_TypeName);
      this.AcceptUntil(VBSymbolType.NewLine);
      if (!this.Context.DesignTimeMode)
        this.Optional(VBSymbolType.NewLine);
      this.Span.CodeGenerator = (ISpanCodeGenerator) new SetBaseTypeCodeGenerator(((string) this.Span.GetContent()).Trim());
      this.Output(SpanKind.Code);
      return false;
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Determines whether the code is an option statement.</summary>
    /// <returns>true if the code is an option statement; otherwise, false.</returns>
    protected virtual bool OptionStatement()
    {
      try
      {
        this.Context.CurrentBlock.Type = new BlockType?(BlockType.Directive);
        this.AcceptAndMoveNext();
        this.AcceptWhile(VBSymbolType.WhiteSpace);
        if (!this.At(VBSymbolType.Identifier))
        {
          if (this.CurrentSymbol != null)
            this.Context.OnError(this.CurrentLocation, string.Format((IFormatProvider) CultureInfo.CurrentCulture, RazorResources.ParseError_Unexpected, (object) this.CurrentSymbol.Content));
          return false;
        }
        SourceLocation currentLocation = this.CurrentLocation;
        string content = this.CurrentSymbol.Content;
        this.AcceptAndMoveNext();
        this.AcceptWhile(VBSymbolType.WhiteSpace);
        bool onOffValue;
        if (this.At(VBKeyword.On))
        {
          this.AcceptAndMoveNext();
          onOffValue = true;
        }
        else if (this.At(VBSymbolType.Identifier))
        {
          if (string.Equals(this.CurrentSymbol.Content, SyntaxConstants.VB.OffKeyword, StringComparison.OrdinalIgnoreCase))
          {
            this.AcceptAndMoveNext();
            onOffValue = false;
          }
          else
          {
            this.Context.OnError(this.CurrentLocation, string.Format((IFormatProvider) CultureInfo.CurrentCulture, RazorResources.ParseError_InvalidOptionValue, (object) content, (object) this.CurrentSymbol.Content));
            this.AcceptAndMoveNext();
            return false;
          }
        }
        else
        {
          if (!this.EndOfFile)
          {
            this.Context.OnError(this.CurrentLocation, string.Format((IFormatProvider) CultureInfo.CurrentCulture, RazorResources.ParseError_Unexpected, (object) this.CurrentSymbol.Content));
            this.AcceptAndMoveNext();
          }
          return false;
        }
        if (string.Equals(content, SyntaxConstants.VB.StrictKeyword, StringComparison.OrdinalIgnoreCase))
          this.Span.CodeGenerator = (ISpanCodeGenerator) SetVBOptionCodeGenerator.Strict(onOffValue);
        else if (string.Equals(content, SyntaxConstants.VB.ExplicitKeyword, StringComparison.OrdinalIgnoreCase))
        {
          this.Span.CodeGenerator = (ISpanCodeGenerator) SetVBOptionCodeGenerator.Explicit(onOffValue);
        }
        else
        {
          this.Span.CodeGenerator = (ISpanCodeGenerator) new SetVBOptionCodeGenerator(content, onOffValue);
          this.Context.OnError(currentLocation, RazorResources.ParseError_UnknownOption, (object) content);
        }
      }
      finally
      {
        if (this.Span.Symbols.Count > 0)
          this.Output(SpanKind.MetaCode);
      }
      return true;
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Determines whether the code imports a statement.</summary>
    /// <returns>true if the code imports a statement; otherwise, false.</returns>
    protected virtual bool ImportsStatement()
    {
      this.Context.CurrentBlock.Type = new BlockType?(BlockType.Directive);
      this.AcceptAndMoveNext();
      this.AcceptVBSpaces();
      if (this.At(VBSymbolType.WhiteSpace) || this.At(VBSymbolType.NewLine))
        this.Context.OnError(this.CurrentLocation, RazorResources.ParseError_NamespaceOrTypeAliasExpected);
      this.AcceptUntil(VBSymbolType.NewLine);
      this.Optional(VBSymbolType.NewLine);
      this.Span.CodeGenerator = (ISpanCodeGenerator) new AddImportCodeGenerator(string.Concat(this.Span.Symbols.Skip<ISymbol>(1).Select<ISymbol, string>((Func<ISymbol, string>) (s => s.Content))), SyntaxConstants.VB.ImportsKeywordLength);
      this.Output(SpanKind.MetaCode);
      return false;
    }

    /// <summary>Ends a termination of statement.</summary>
    /// <returns>The function that ends the termination.</returns>
    /// <param name="keyword">The keyword.</param>
    /// <param name="supportsExit">true if the termination supports exit; otherwise, false.</param>
    /// <param name="supportsContinue">true if the termination supports continue; otherwise, false.</param>
    protected virtual Func<bool> EndTerminatedStatement(
      VBKeyword keyword,
      bool supportsExit,
      bool supportsContinue)
    {
      return this.EndTerminatedStatement(keyword, supportsExit, supportsContinue, keyword.ToString());
    }

    /// <summary>Ends a termination of statement.</summary>
    /// <returns>The function that ends the termination.</returns>
    /// <param name="keyword">The keyword.</param>
    /// <param name="supportsExit">true if the termination supports exit; otherwise, false.</param>
    /// <param name="supportsContinue">true if the termination supports continue; otherwise, false.</param>
    /// <param name="blockName">The block name.</param>
    protected virtual Func<bool> EndTerminatedStatement(
      VBKeyword keyword,
      bool supportsExit,
      bool supportsContinue,
      string blockName)
    {
      return (Func<bool>) (() =>
      {
        using (this.PushSpanConfig(this.StatementBlockSpanConfiguration((SpanCodeGenerator) new StatementCodeGenerator())))
        {
          SourceLocation currentLocation = this.CurrentLocation;
          this.AcceptAndMoveNext();
          while (!this.EndOfFile)
          {
            VBSymbol vbSymbol = this.AcceptWhiteSpaceInLines();
            if (this.IsAtEmbeddedTransition(true, true))
            {
              this.HandleEmbeddedTransition(vbSymbol);
            }
            else
            {
              this.Accept(vbSymbol);
              if (supportsExit && this.At(VBKeyword.Exit) || supportsContinue && this.At(VBKeyword.Continue))
                this.HandleExitOrContinue(keyword);
              else if (this.At(VBKeyword.End))
              {
                this.AcceptAndMoveNext();
                this.AcceptVBSpaces();
                if (this.At(keyword))
                {
                  this.AcceptAndMoveNext();
                  if (!this.Context.DesignTimeMode)
                    this.Optional(VBSymbolType.NewLine);
                  this.Span.EditHandler.AcceptedCharacters = AcceptedCharacters.None;
                  return false;
                }
              }
              else if (this.At(keyword))
              {
                int num = this.EndTerminatedStatement(keyword, supportsExit, supportsContinue)() ? 1 : 0;
              }
              else if (!this.EndOfFile)
                this.AcceptAndMoveNext();
            }
          }
          this.Context.OnError(currentLocation, RazorResources.ParseError_BlockNotTerminated, (object) blockName, (object) (VBKeyword.End.ToString() + " " + (object) keyword));
          return false;
        }
      });
    }

    /// <summary>Indicates a keyword that terminates a statement.</summary>
    /// <returns>The function that terminates the statement.</returns>
    /// <param name="start">The start.</param>
    /// <param name="terminator">The terminator.</param>
    /// <param name="supportsExit">true if the termination supports exit; otherwise, false.</param>
    /// <param name="supportsContinue">true if the termination supports continue; otherwise, false.</param>
    protected virtual Func<bool> KeywordTerminatedStatement(
      VBKeyword start,
      VBKeyword terminator,
      bool supportsExit,
      bool supportsContinue)
    {
      return (Func<bool>) (() =>
      {
        using (this.PushSpanConfig(this.StatementBlockSpanConfiguration((SpanCodeGenerator) new StatementCodeGenerator())))
        {
          SourceLocation currentLocation = this.CurrentLocation;
          this.AcceptAndMoveNext();
          while (!this.EndOfFile)
          {
            VBSymbol vbSymbol = this.AcceptWhiteSpaceInLines();
            if (this.IsAtEmbeddedTransition(true, true))
            {
              this.HandleEmbeddedTransition(vbSymbol);
            }
            else
            {
              this.Accept(vbSymbol);
              if (supportsExit && this.At(VBKeyword.Exit) || supportsContinue && this.At(VBKeyword.Continue))
                this.HandleExitOrContinue(start);
              else if (this.At(start))
              {
                int num = this.KeywordTerminatedStatement(start, terminator, supportsExit, supportsContinue)() ? 1 : 0;
              }
              else
              {
                if (this.At(terminator))
                {
                  this.AcceptUntil(VBSymbolType.NewLine);
                  this.Optional(VBSymbolType.NewLine);
                  this.Span.EditHandler.AcceptedCharacters = AcceptedCharacters.AnyExceptNewline;
                  return false;
                }
                if (!this.EndOfFile)
                  this.AcceptAndMoveNext();
              }
            }
          }
          this.Context.OnError(currentLocation, RazorResources.ParseError_BlockNotTerminated, (object) start, (object) terminator);
          return false;
        }
      });
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Indicates the code that handles the Exit or Continue keyword.</summary>
    /// <param name="keyword">The keyword.</param>
    protected void HandleExitOrContinue(VBKeyword keyword)
    {
      this.AcceptAndMoveNext();
      this.AcceptWhile(VBSymbolType.WhiteSpace);
      this.Optional(keyword);
    }
  }
}
